package com.wngbms.asyncsocket.server;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousChannelGroup;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;

public class AioServerDemo {

    static Logger log = LoggerFactory.getLogger(AioServerDemo.class);

    public static void main(String[] args) throws IOException {
        ThreadPoolExecutor groupExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(5, new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r);
//                thread.setName("");
                return thread;
            }
        });

        AsynchronousChannelGroup channelGroup = AsynchronousChannelGroup.withThreadPool(groupExecutor);
        AsynchronousServerSocketChannel serverSocketChannel = AsynchronousServerSocketChannel.open(channelGroup);

//        serverSocketChannel.bind(new InetSocketAddress("192.168.31.79", 8888));
//        serverSocketChannel.bind(new InetSocketAddress("192.168.75.1", 8888));
        serverSocketChannel.bind(new InetSocketAddress("127.0.0.1", 8888));

        serverSocketChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {
            int a = 5;

            @Override
            public void completed(AsynchronousSocketChannel socketChannel, Void attachment) {
                try {
                    InetSocketAddress remoteAddress = (InetSocketAddress) socketChannel.getRemoteAddress();
                    log.info("建立客户端链接:{}", remoteAddress);

                    socketChannel.setOption(StandardSocketOptions.SO_SNDBUF, 64 * 1024);
                    Thread.sleep(2000);

                    for (int i = 0; i < 30; i++) {
                        ByteBuffer wrap = ByteBuffer.wrap("miui\n".getBytes());
                        Future<Integer> write = socketChannel.write(wrap);
                        while (!write.isDone()) {
                            Thread.sleep(10);
                        }
                        Thread.sleep(800);
                    }

                    log.info("服务端发送完成");
                    socketChannel.close();
                } catch (IOException | InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    log.info("CompletionHandler:[{}] [{}]", this.getClass(), this.a);
                    serverSocketChannel.accept(null, this);
                }
            }

            @Override
            public void failed(Throwable exc, Void attachment) {
                exc.printStackTrace();
            }
        });

        log.info("server started");
        try {
            Thread.sleep(Integer.MAX_VALUE);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
